package com.winning.pmph.ctrl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.winning.pmph.entity.*;
import com.winning.pmph.service.*;
import com.winning.pmph.utils.ApplicationContextUtil;
import com.winning.pmph.utils.UploadFileUtil;
import com.winning.pmph.vo.CascaderOption;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.stream.Collectors;

@Api(value = "知识体系管理/分类标签")
@Slf4j
@RestController
@RequestMapping("/pmph/action/tag")
public class TagCtrl {
    @Resource
    private TagService service;
    @Resource
    private CalculatorService calculatorService;
    @Resource
    private KnowledgeLibService knowledgeLibService;
    @Resource
    private KnowledgeLibFieldService knowledgeLibFieldService;
    @Resource
    private TempKnowledgeFieldService tempKnowledgeFieldService;
    @Resource
    private ReleasedKnowledgeFieldService releasedKnowledgeFieldService;
    /**
     * 查询顶级标签集合
     */
    @ApiOperation(value = "selectTopTagList", notes = "专查询顶级标签集合接口")
    @GetMapping("selectTopTagList")
    public List<Tag> selectTopTagList() {
        return service.lambdaQuery().eq(Tag::getLevel, 1).orderByAsc(Tag::getIndex).list();
    }

    /**
     * 根据顶级标签, 查询所有子标签
     */
    @ApiOperation(value = "selectSubTagListByTopTagId", notes = "根据顶级标签, 查询所有子标签")
    @GetMapping("selectSubTagListByTopTagId")
    public List<Tag> selectSubTagListByTopTagId(String topTagId) {
        return service.selectSubTagListByTopTagId(topTagId);
    }

    /**
     * 根据顶级标签, 查询所有子标签
     */
    @ApiOperation(value = "selectSubTagTreeByTopTagIdWithNameAndCodeAsName", notes = "根据顶级标签, 查询所有子标签")
    @GetMapping("selectSubTagTreeByTopTagIdWithNameAndCodeAsName")
    public List<Tag> selectSubTagTreeByTopTagIdWithNameAndCodeAsName(String topTagId) {
        return service.selectSubTagTreeByTopTagIdWithNameAndCodeAsName(topTagId);
    }

    /**
     * 根据图书分类信息
     */
    @ApiOperation(value = "selectBookSubTagTree", notes = "查询图书分类信息")
    @GetMapping("selectBookSubTagTree")
    public List<Tag> selectBookSubTagTree() {
        Tag bookTopTag = service.getBaseMapper().selectBeanByWherePart("level = 1 and name = '图书分类'");
        return service.selectSubTagTreeByTopTagId(bookTopTag.getId());
    }

    @ApiOperation(value = "uploadTagFile", notes = "分类标签上传下级分类")
    @PostMapping("uploadTagFile")
    public void uploadTagFile(MultipartFile file, @RequestParam String supTagId) {
        String path = ApplicationContextUtil.BASE_DOWN_FORDER + "file/tag/" + supTagId + "/";
        UploadFileUtil.uploadFile(file, path, false);
    }

    @ApiOperation(value = "uploadAndInsertTagFile", notes = "分类标签上传接口")
    @PostMapping("uploadAndInsertTagFile")
    public void uploadAndInsertTagFile(MultipartFile file, @RequestParam("supTagId") String supTagId) {
        String path = ApplicationContextUtil.BASE_DOWN_FORDER + "file/tag/" + supTagId + "/";
        UploadFileUtil.uploadFile(file, path, false);
        Tag tag = service.getById(supTagId);
        service.saveTag(tag);
    }

    @ApiOperation(value = "removeTagFile", notes = "移除分类标签上传文件")
    @GetMapping("removeTagFile")
    public void removeTagFile(String supTagId,String tagFileName) {
        String path = ApplicationContextUtil.BASE_DOWN_FORDER + "file/tag/" + supTagId + "/" + tagFileName;
        new File(path).delete();
    }

    @ApiOperation(value = "saveTag", notes = "保存分类标签接口")
    @PostMapping("saveTag")
    public void saveTag( String tag) {
        Tag tags = JSON.parseObject(tag, Tag.class);
        service.saveTag(tags);
    }

    @ApiOperation(value = "deleteTopTag", notes = "删除顶级分类标签接口")
    @PostMapping("deleteTopTag")
    public void deleteTopTag(String tag) {
        Tag tags = JSON.parseObject(tag, Tag.class);
        // 查看是否有数据库引用当前顶级标签;
        List<KnowledgeLibField> knowledgeLibFields = knowledgeLibFieldService.lambdaQuery().eq(KnowledgeLibField::getKindValue, tags.getId()).list();
        if (CollectionUtils.isNotEmpty(knowledgeLibFields)) {
            List<KnowledgeLib> knowledgeLibs = knowledgeLibService.lambdaQuery()
                    .in(KnowledgeLib::getId, knowledgeLibFields.stream().map(KnowledgeLibField::getKnowledgeLibId).collect(Collectors.toSet())).list();
            throw new RuntimeException("标签已被" + knowledgeLibs.stream().map(KnowledgeLib::getName).collect(Collectors.joining(",", "(", ")")) + "引用, 不能删除");
        }
        String whereStr = " tag_id = '" + tags.getId() + "'";
        List<MedicalCalculatorLibField> medicalCalculatorLibFields = calculatorService.getMedicalCalculatorLibFieldByWhereStr(whereStr);
        if (medicalCalculatorLibFields.size() > 0) {
            throw new RuntimeException("标签已被医学计算器库引用, 不能删除");
        }
        service.deleteTopTag(tags);
    }

    @ApiOperation(value = "deleteSubTag", notes = "删除分类标签及子标签")
    @PostMapping("deleteSubTag")
    public void deleteSubTag(String tag) {
        Tag tags = JSON.parseObject(tag, Tag.class);
        // 查看是否有数据库引用当前顶级标签;
        // 利用 kind == 2 and property like '%"id"%'

        List<TempKnowledgeField> tempKnowledgeFields = tempKnowledgeFieldService.getBaseMapper().selectBeansByWherePart("kind = " + KnowledgeLibField.FIELD_KIND_REFERENCE + " and property like '%\"" + tags.getId() + "\"%'");
        if (CollectionUtils.isNotEmpty(tempKnowledgeFields)) {
            throw new RuntimeException("标签已被草稿库知识引用, 不能删除");
        }
        List<ReleasedKnowledgeField> releasedKnowledgeFields = releasedKnowledgeFieldService.getBaseMapper().selectBeansByWherePart("kind = " + KnowledgeLibField.FIELD_KIND_REFERENCE + " and property like '%\"" + tags.getId() + "\"%'");
        if (CollectionUtils.isNotEmpty(releasedKnowledgeFields)) {
            throw new RuntimeException("标签已被正式库知识引用, 不能删除");
        }
        String whereStr = " kind = 1 and property like '%\"" + tags.getId() + "\"%'";
        List<MedicalCalculatorField> medicalCalculatorFields = calculatorService.getMedicalCalculatorField(whereStr);
        if (medicalCalculatorFields.size() > 0) {
            throw new RuntimeException("标签已被草稿库计算器引用, 不能删除");
        }
        String whereStr1 = " kind = 1 and property like '%\"" + tags.getId() + "\"%'";
        List<ReleasedMedicalCalculatorField> releasedMedicalCalculatorFields = calculatorService.getReleasedMedicalCalculatorFieldByWhereStr(whereStr1);
        if (releasedMedicalCalculatorFields.size() > 0) {
            throw new RuntimeException("标签已被正式库计算器引用, 不能删除");
        }
        service.deleteSubTag(tags);
    }

    @ApiOperation(value = "topTagMoveUp", notes = "顶级标签上移接口")
    @PostMapping("topTagMoveUp")
    public void topTagMoveUp(@RequestPart Tag tag,@RequestPart Tag preTag) {
        service.topTagMoveUp(tag, preTag);
    }

    @ApiOperation(value = "subTagMoveUp", notes = "二级及以下标签上移接口")
    @PostMapping("subTagMoveUp")
    public void subTagMoveUp(String tag,String preTag) {
        Tag tags= JSON.parseObject(tag, Tag.class);
        Tag preTags = JSON.parseObject(preTag, Tag.class);
        service.subTagMoveUp(tags, preTags);
    }

    @ApiOperation(value = "transferTag", notes = "分类标签转移接口")
    @PostMapping("transferTag")
    public void transferTag(String tag) {
        Tag tags = JSON.parseObject(tag, Tag.class);
        service.recursiveTransferTag(tags);
    }

    @ApiOperation(value = "transferKnowledge", notes = "分类标签转移知识接口")
    @PostMapping("transferKnowledge")
    public void transferKnowledge(String selectedTagIdOri,String selectedTagId) {
        if (!StringUtils.equals(selectedTagIdOri, selectedTagId)) {
            service.transferKnowledge(selectedTagIdOri, selectedTagId);
        }
    }

    @ApiOperation(value = "downloadImportTagTemplate", notes = "分类标签下载导入模板接口")
    @GetMapping("downloadImportTagTemplate")
    public void downloadImportTagTemplate(HttpServletResponse response) throws UnsupportedEncodingException {
        // 创建一个Excel文件
        XSSFWorkbook wb = new XSSFWorkbook();
        // 创建第一个工作表
        XSSFSheet sheet = wb.createSheet();
        // 添加表头行
        XSSFRow xssfRow = sheet.createRow(0);
        // 添加表头内容
        XSSFCell headCell = xssfRow.createCell(0);
        headCell.setCellValue("分类名称");
        headCell = xssfRow.createCell(1);
        headCell.setCellValue("分类编码");

        XSSFRow row1 = sheet.createRow(1);
        XSSFCell cell10 = row1.createCell(0);
        cell10.setCellValue("症状");
        XSSFCell cell11 = row1.createCell(1);
        cell11.setCellValue("ZZTZ.001");

        XSSFRow row2 = sheet.createRow(2);
        XSSFCell cell20 = row2.createCell(0);
        cell20.setCellValue("体征");
        XSSFCell cell21 = row2.createCell(1);
        cell21.setCellValue("ZZTZ.002");

        XSSFRow row3 = sheet.createRow(3);
        XSSFCell cell30 = row3.createCell(0);
        cell30.setCellValue("一般症状");
        XSSFCell cell31 = row3.createCell(1);
        cell31.setCellValue("ZZTZ.001.001");

        XSSFRow row4 = sheet.createRow(4);
        XSSFCell cell40 = row4.createCell(0);
        cell40.setCellValue("全身状态");
        XSSFCell cell41 = row4.createCell(1);
        cell41.setCellValue("ZZTZ.002.001");

        XSSFRow row5 = sheet.createRow(5);
        XSSFCell cell50 = row5.createCell(0);
        cell50.setCellValue("营养状态");
        XSSFCell cell51 = row5.createCell(1);
        cell51.setCellValue("ZZTZ.002.001.001");

        sheet.createRow(6).createCell(0).setCellValue("说明1: 导入当前选中标签下的子分类, 后台按照分类编码组织层次结构, 如 ZZTZ.001.001 父编码为: ZZTZ.001");
        sheet.createRow(7).createCell(0).setCellValue("说明2: 按照表格行的顺序组织导入子分类的排序, 父分类必须出现在子标签上方");
        sheet.createRow(8).createCell(0).setCellValue("说明3: 后台按照导入文件的编码组织层次结构, 并根据平台默认逻辑生成编码, 导入前请删除示例及说明");

        response.setContentType("application/xlsx;charset=UTF-8");
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("子标签导入模板.xlsx", "UTF-8"));
        try {
            wb.write(response.getOutputStream());
            response.getOutputStream().close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    @ApiOperation(value = "downloadTagTree", notes = "根据id下载标签及子标签")
    @GetMapping("downloadTagTree")
    public void downloadTagTree(String tagId,HttpServletResponse response) throws UnsupportedEncodingException {
        // 递归查询标签及子标签;
        List<Tag> tags = service.getBaseMapper().executeMultiSelect(
                "select sub.*, sup.tag_code as parent_code " +
                        " from tag sub left join tag sup on sub.PARENT_ID = sup.id " +
                        " where sub.root_id = '" + tagId + "' order by sub.level, sub.`index`");
        // 创建一个Excel文件
        XSSFWorkbook wb = new XSSFWorkbook();
        // 创建第一个工作表
        XSSFSheet sheet = wb.createSheet();
        // 添加表头行
        XSSFRow headRow = sheet.createRow(0);
        // 添加表头内容
        XSSFCell headCell0 = headRow.createCell(0);
        headCell0.setCellValue("分类名称");
        XSSFCell headCell1 = headRow.createCell(1);
        headCell1.setCellValue("分类编码");
        XSSFCell headCell2 = headRow.createCell(2);
        headCell2.setCellValue("上级分类编码");
        for (int i = 0; i < tags.size(); i++) {
            Tag tag = tags.get(i);
            XSSFRow cntRow = sheet.createRow(i + 1);
            XSSFCell cntRowCell0 = cntRow.createCell(0);
            cntRowCell0.setCellValue(tag.getName());
            XSSFCell cntRowCell1 = cntRow.createCell(1);
            cntRowCell1.setCellValue(tag.getTagCode());
            XSSFCell cntRowCell2 = cntRow.createCell(2);
            cntRowCell2.setCellValue(tag.getParentCode());
        }
        response.setContentType("application/xlsx;charset=UTF-8");
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(tags.get(0).getName() + "及子分类标签.xlsx", "UTF-8"));
        try {
            wb.write(response.getOutputStream());
            response.getOutputStream().close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    @ApiOperation(value = "syncTopTag", notes = "分类标签推送接口")
    @GetMapping("syncTopTag")
    public void syncTopTag(String topTagId) {
        service.syncTopTag(topTagId);
    }

    @ApiOperation(value = "selectTagCascaderOptions", notes = "查询tag标签树结构接口")
    @GetMapping("selectTagCascaderOptions")
    public List<CascaderOption> selectTagCascaderOptions() {
        List<Tag> result = service.selectTagTree();
        return JSONArray.parseArray(JSON.toJSONString(result), CascaderOption.class);
    }
}
